package com.working.libview.widget

import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.PointF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.core.animation.doOnEnd
import androidx.core.graphics.toColorInt
import androidx.core.util.Pools
import com.noober.background.drawable.DrawableCreator
import com.working.libcommon.exts.cast
import dp
import kotlin.random.Random

class CoolTouchLayout : FrameLayout {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes)

    init {
        isFocusable = true
        isClickable = true
        setWillNotDraw(false)
    }

    var touchPoint: PointF = PointF()
    private fun randomOffset() = Random.nextInt(-effectRadius.toInt(), effectRadius.toInt())

    @SuppressLint("ClickableViewAccessibility")
    override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
        touchPoint.x = event?.x ?: 0f
        touchPoint.y = event?.y ?: 0f
        when (event?.action) {
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> clearEffects()
            else -> startEffects()
        }
        return super.dispatchTouchEvent(event)
    }


    private val mPools = Pools.SimplePool<View>(15)
    private var effectMode = true
    private val effectRadius = 20f.dp
    private val effectColor = "#03DAC5".toColorInt()

    private fun generateEffectView() = mPools.acquire() ?: View(context).apply {
        val mode = Random.nextBoolean()
        background = if (mode)
            DrawableCreator.Builder()
                .setStrokeWidth(2f.dp)
                .setSizeHeight(effectRadius)
                .setSizeWidth(effectRadius)
                .setSolidColor(Color.TRANSPARENT)
                .setStrokeColor(effectColor)
                .build()
        else DrawableCreator.Builder()
            .setSizeHeight(effectRadius)
            .setSizeWidth(effectRadius)
            .setSolidColor(effectColor)
            .build()
        val animator = if (mode) {
            ValueAnimator.ofFloat(1f, 0f).let { valueAnimator ->
                valueAnimator.doOnEnd {
                    removeView(this)
                    mPools.release(this)
                }
                valueAnimator.addUpdateListener {
                    this.alpha = it.animatedValue as Float
                    this.scaleX = (2 - it.animatedValue as Float)
                    this.scaleY = (2 - it.animatedValue as Float)
                }
                valueAnimator
            }
        } else {
            ValueAnimator.ofFloat(1f, 0f).let { valueAnimator ->
                valueAnimator.doOnEnd {
                    removeView(this)
                    mPools.release(this)
                }
                valueAnimator.addUpdateListener {
                    this.alpha = it.animatedValue as Float
                    this.scaleX = it.animatedValue as Float
                    this.scaleY = it.animatedValue as Float
                }
                valueAnimator
            }
        }
        animator.duration = 1000
        tag = animator
        effectMode = effectMode.not()
    }

    private fun clearEffects() {

    }


    private fun startEffects() {
        val view = generateEffectView()
        val anim = view.tag.cast<Animator>()
        addView(view, LayoutParams(effectRadius.toInt(), effectRadius.toInt()).apply {
            topMargin = (touchPoint.y - effectRadius / 2).toInt() + randomOffset()
            leftMargin = (touchPoint.x - effectRadius / 2).toInt() + randomOffset()
        })
        anim?.start()
    }

}